/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Foundation Framework
 * Version 2.10
 * 
 * Data Object Base Class
 *      Provides a base definition for data-aware interaction objects of specific types.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
using System;
using System.Data;
using System.Data.Common;

namespace Adaptive.Foundation.Data
{
    /// <summary>
    /// Provides a base definition for data-aware interaction objects of specific types.
    /// </summary>
    /// <typeparam name="T">
    /// The type of structure used in data communications.
    /// </typeparam>
    public abstract class DataObjectBase<T> : DisposableObjectBase
    {
        /*--------------------------------------------------------------------------------
		 * Public Event Declarations
		 *------------------------------------------------------------------------------*/
        #region Public Event Declarations
        /// <summary>
        /// Occurs when a data exception is encountered.
        /// </summary>
        public event ExceptionEventHandler DataException;
        /// <summary>
        /// Occurs when a general, non-data exception is caught.
        /// </summary>
        public event ExceptionEventHandler ExceptionCaught;
        #endregion

        /*--------------------------------------------------------------------------------
		 * Private Member Declarations
		 *------------------------------------------------------------------------------*/
        #region Private Member Declarations
        /// <summary>
        /// The data access instance.
        /// </summary>
        private DataActorBase _dataAccess;
        #endregion

        /*--------------------------------------------------------------------------------
         * Constructor / Dispose / Destructor Methods
		 *------------------------------------------------------------------------------*/
        #region Constructor / Dispose / Destructor Methods
        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <remarks>
        /// This is the default constructor.
        /// </remarks>
        protected DataObjectBase()
        {
            _dataAccess = ApplicationDatabaseFactory.CreateDataActor();
        }
        /// <summary>
        /// Deallocates internally allocated objectts.
        /// </summary>
        /// <param name="disposing">
        /// A value indicating whether the object is being disposed.
        /// </param>
        protected override void Dispose(bool disposing)
        {
            if ((!Disposed) && (disposing))
            {
                if (_dataAccess != null)
                    _dataAccess.Dispose();
            }
            _dataAccess = null;
            base.Dispose(disposing);
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Protected Methods / Functions / Overrides
		 *------------------------------------------------------------------------------*/
        #region Protected Methods / Functions / Overrides
        /// <summary>
        /// Inserts a new record into the database.
        /// </summary>
        /// <param name="dataInstance">The data access object.</param>
        /// <param name="newRecordDefinition">A record to be inserted.</param>
        /// <returns>
        /// <b>true</b> if the insert is successful; otherwise, returns <b>false</b>.
        /// </returns>
        protected abstract bool CreateNewRecordData(DataActorBase dataInstance, T newRecordDefinition);
        /// <summary>
        /// Reads record(s) from the database.
        /// </summary>
        /// <param name="dataInstance">The data access object.</param>
        /// <param name="parameterDefinition">
        /// A record definition containing the search parameters.
        /// </param>
        /// <returns>
        /// A <see cref="DataTable"/> with the results if successful; otherwise, returns <b>null</b>.
        /// </returns>
        protected abstract DataTable ReadRecordData(DataActorBase dataInstance, T parameterDefinition);
        /// <summary>
        /// Updates an existing record in the database.
        /// </summary>
        /// <param name="dataInstance">The data access object.</param>
        /// <param name="oldRecordDefinition">The original data content.</param>
        /// <param name="newRecordDefinition">The new data content.</param>
        /// <returns>
        /// <b>true</b> if the update is successful; otherwise, returns <b>false</b>.
        /// </returns>
        protected abstract bool UpdateRecordData(DataActorBase dataInstance, T oldRecordDefinition, T newRecordDefinition);
        /// <summary>
        /// Deletes a record from the database.
        /// </summary>
        /// <param name="dataInstance">The data access object.</param>
        /// <param name="parameterDefinition">A record to be deleted.</param>
        /// <returns>
        /// <b>true</b> if the delete is successful; otherwise, returns <b>false</b>.
        /// </returns>
        protected abstract bool DeleteRecordData(DataActorBase dataInstance, T parameterDefinition);
        /// <summary>
        /// Popautes the specified data record with th supplied table data.
        /// </summary>
        /// <param name="dataContentSource">A data table to be read from.</param>
        /// <param name="newRecordDefinition">The structure to be populated.</param>
        protected abstract void PopulateData(DataTable dataContentSource, ref T newRecordDefinition);
        /// <summary>
        /// Popautes the specified data records with th supplied table data.
        /// </summary>
        /// <param name="dataContentSource">A data table to be read from.</param>
        /// <param name="newRecordDefinition">An array of structures to be populated.</param>
        protected abstract void PopulateData(DataTable dataContentSource, ref T[] newRecordDefinition);
        /// <summary>
        /// Raises the <see cref="DataException"/> event.
        /// </summary>
        /// <param name="e">
        /// An <see cref="ExceptionEventArgs"/> event arguments instance containing the 
        /// exception that was caught.
        /// </param>
        protected virtual void OnDataException(ExceptionEventArgs e)
        {
            if (DataException != null)
                DataException(this, e);
        }
        /// <summary>
        /// Raises the <see cref="E:OnExceptionCaught"/> event.
        /// </summary>
        /// <param name="e">The <see cref="Adaptive.Foundation.ExceptionEventArgs"/> instance containing the event data.</param>
        protected virtual void OnExceptionCaught(ExceptionEventArgs e)
        {
            if (ExceptionCaught != null)
                ExceptionCaught(this, e);
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Methods / Functions
		 *------------------------------------------------------------------------------*/
        #region Public Methods / Functions
        /// <summary>
        /// Inserts a new record into the database.
        /// </summary>
        /// <param name="newRecordDefinition">A record to be inserted.</param>
        /// <returns>
        /// <b>true</b> if the insert is successful; otherwise, returns <b>false</b>.
        /// </returns>
        public bool Create(T newRecordDefinition)
        {
            bool returnValue = false;               //Return value.

            try
            {
                returnValue = CreateNewRecordData(_dataAccess, newRecordDefinition);
            }
            catch (DataException dataEx)
            {
                OnDataException(new ExceptionEventArgs(dataEx));
            }
            catch(Exception ex)
            {
                OnExceptionCaught(new ExceptionEventArgs(ex));
            }
            return returnValue;
        }
        /// <summary>
        /// Reads record(s) from the database.
        /// </summary>
        /// <param name="parameterDefinition">
        /// A record definition containing the search parameters.
        /// </param>
        /// <returns>
        /// A <see cref="DataTable"/> with the results if successful; otherwise, returns <b>null</b>.
        /// </returns>
        public DataTable Read(T parameterDefinition)
        {
            DataTable returnValue = null;               //Return value.

            try
            {
                returnValue =  ReadRecordData(_dataAccess, parameterDefinition);
            }
            catch (DataException dataEx)
            {
                OnDataException(new ExceptionEventArgs(dataEx));
            }
            catch(Exception ex)
            {
                OnExceptionCaught(new ExceptionEventArgs(ex));
            }
            return returnValue;
        }
        /// <summary>
        /// Updates an existing record in the database.
        /// </summary>
        /// <param name="oldRecordDefinition">The original data content.</param>
        /// <param name="newRecordDefinition">The new data content.</param>
        /// <returns>
        /// <b>true</b> if the update is successful; otherwise, returns <b>false</b>.
        /// </returns>
        public bool Update(T oldRecordDefinition, T newRecordDefinition)
        {
            bool returnValue = false;               //Return value.

            try
            {
                returnValue = UpdateRecordData(_dataAccess, oldRecordDefinition, newRecordDefinition);
            }
            catch (DataException dataEx)
            {
                OnDataException(new ExceptionEventArgs(dataEx));
            }
            catch (Exception ex)
            {
                OnExceptionCaught(new ExceptionEventArgs(ex));
            }
            return returnValue;
        }
        /// <summary>
        /// Deletes a record from the database.
        /// </summary>
        /// <param name="parameterDefinition">A record to be deleted.</param>
        /// <returns>
        /// <b>true</b> if the delete is successful; otherwise, returns <b>false</b>.
        /// </returns>
        public bool Delete(T parameterDefinition)
        {
            bool returnValue = false;               //Return value.

            try
            {
                returnValue = DeleteRecordData(_dataAccess, parameterDefinition);
            }
            catch (DataException dataEx)
            {
                OnDataException(new ExceptionEventArgs(dataEx));
            }
            catch (Exception ex)
            {
                OnExceptionCaught(new ExceptionEventArgs(ex));
            }
            return returnValue;
        }
        /// <summary>
        /// Translates a boolean to a yes/no character value.
        /// </summary>
        /// <param name="original">The value to be translated.</param>
        /// <returns>
        /// "Y": for true; "N" for false.
        /// </returns>
        public string TranslateToYN(bool original)
        {
            if (original)
                return "Y";
            else
                return "N";
        }
        /// <summary>
        /// Translates a boolean to a yes/no character value.
        /// </summary>
        /// <param name="original">The value to be translated.</param>
        /// <returns>
        /// "Y": for true; "N" for false.
        /// </returns>
        public bool TranslateFromYN(string original)
        {
            bool returnValue = false;

            if ((original != null) && (original.Length > 0))
            {
                returnValue = (original.Substring(0, 1).Trim().ToLower() == "y");
            }
            return returnValue;
        }
        /// <summary>
        /// Translates the specified date value to the integer format used 
        /// in the DB.
        /// </summary>
        /// <param name="originalDate"></param>
        /// <returns></returns>
        public int TranslateToDateInteger(DateTime originalDate)
        {
            int returnValue = 0;

            try
            {
                returnValue = Convert.ToInt32(originalDate.ToString("yyyyMMdd"));
            }
            catch (Exception ex)
            {
                OnExceptionCaught(new ExceptionEventArgs(ex));
            }
            return returnValue;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dateValue"></param>
        /// <returns></returns>
        public DateTime TranslateFromDateInteger(int dateValue)
        {
            DateTime returnValue = DateTime.MinValue;

            string item = dateValue.ToString().Trim();
            if (item.Length >= 8)
            {
                try
                {
                    returnValue = DateTime.Parse(item.Substring(4, 2) + "/" + item.Substring(6, 2) + "/" + item.Substring(0, 4));
                }
                catch (Exception ex)
                {
                    OnExceptionCaught(new ExceptionEventArgs(ex));
                }
            }
            return returnValue;
        }
        /// <summary>
        /// Translates a null string into an empty string.
        /// </summary>
        /// <param name="original">
        /// The value to be processed.
        /// </param>
        /// <returns>
        /// A an empty string if the original value is null; otherwise, returns the original string.
        /// </returns>
        public static string NotNullString(string original)
        {
            if (original != null)
                return original;
            else
                return string.Empty;
        }
        #endregion
    }
}
